(function ($) {
    var utils = {
            //获取uuid唯一值，用于识别控件以及附件数据的
            uuid: function () {
                function S4() {
                    return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
                }
                return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
            },
            //初始化时格式化化默认数据的
            formatData: function (options) {
                var data = [];
                if (this.isJSON(options.value)) {
                    options.value = JSON.parse(options.value);
                }
                if (!Array.isArray(options.value) && options.value && (options.value.mid || options.value.fileId)) {
                    data.push(options.value);
                } else if (Array.isArray(options.value)) {
                    data = options.value;
                }
                options.value = {};
                for (var i = 0; i < data.length; i++) {
                    options.value[this.uuid()] = this.getData(data[i], options);
                }
            },
            //格式化数据
            getData: function (item, options) {
                return {
                    id: item[options.formmat.id] || item.mid,
                    name: item[options.formmat.name] || item.fileName,
                    thumb: item[options.formmat.thumb] || item.thumbUrl,
                    download: item[options.formmat.download] || item.htmlUrl,
					fileType: item[options.formmat.fileType] || item.fileType,
                }
            },
            changeValue: function (target) {
                var state = $.data(target, "filebox"),
                    options = state.options,
                    mid = '';
                if (options.multiple) {
                    var ids = [];
                    for (var key in options.value) {
                        if (options.value[key].id) ids.push(options.value[key].id);
                    }
                    if (ids.length > 0) mid = JSON.stringify(ids);
                } else {
                    for (var key in options.value) {
                        if (options.value[key].id) mid = options.value[key].id;
                    }
                }
                $(target).textbox("setValue", mid);
                $(target).next().find(".validatebox-text:not(:disabled)").mouseenter();
                if (options.onDone) options.onDone(fileboxCreate.getValue(options));
            },
            //判断是不是JSON字符串
            isJSON: function (str) {
                if (typeof str == 'string') {
                    try {
                        var obj = JSON.parse(str);
                        return true;
                    } catch (e) {
                        return false;
                    }
                }
                return false;
            },
            //为了兼容上个版本的数据数据
            formatInitData: function (obj) {
                var data = [],
                    fileType = ["mid", "fileName", "thumbUrl", "htmlUrl", "fileType"];
                for (var i = 0; i < fileType.length; i++) {
                    if (this.isJSON(obj[fileType[i]])) {
                        var list = JSON.parse(obj[fileType[i]]);
                        for (var j = 0; j < list.length; j++) {
                            if (!data[j]) data[j] = {};
                            data[j][fileType[i]] = list[j];
                        }
                    }
                }
                return data.length > 0 ? data : obj;
            },
        },
        ajaxUtil = {
            progress: {},
            postFile: function (file, uuid, state) {
                var options = state.options;
                if (!this.progress[uuid])
                    this.progress[uuid] = {
                        file: file,
                        progress: 0,
                        value: 0,
                        ajax: null,
                        interval: null,
                        start: false,
                    };
                else
                    this.progress[uuid].ajax.abort();
                this.progress[uuid].ajax = null;
                this.progress[uuid].value = 0;
                this.progress[uuid].progress = 0;
                var formData = new FormData();
                formData.append("modelName", options.modelName);
                formData.append("files[]", file);
                this.progress[uuid].ajax = $.ajax({
                    url: options.url,
                    type: "post",
                    dataType: "json",
                    data: formData,
                    headers: options.headers,
                    processData: false, // ⑧告诉jQuery不要去处理发送的数据
                    contentType: false, // ⑨告诉jQuery不要去设置Content-Type请求头});
                    xhr: function () {
                        return ajaxUtil.xhr(uuid, state)
                    },
                    success: function (result) {
                        if (result.success && result.obj.length > 0) {
                            ajaxUtil.success(uuid, result.obj[0], state)
                        } else {
                            ajaxUtil.error(uuid, result.msg, state);
                        }
                    },
                    error: function (error) {
                        ajaxUtil.error(uuid, error, state)
                    },
                })
            },
            xhr: function (uuid, state) {
                var xhr = new XMLHttpRequest();
                //使用XMLHttpRequest.upload监听上传过程，注册progress事件，打印回调函数中的event事件
                xhr.upload.addEventListener('progress', function (e) {
                    //loaded代表上传了多少
                    //total代表总数为多少
                    var progressRate = (e.loaded / e.total) * 100;
                    if (progressRate > 80) progressRate = 80;
                    ajaxUtil.setProgress(uuid, progressRate, state);
                });
                return xhr;
            },
            success: function (uuid, fileInfo, state) {
                delete fileInfo["@type"];
                this.progress[uuid].ajax = null;
                state.options.value[uuid] = utils.getData(fileInfo, state.options);
                if (state.options.boxtype == 'image') {
                    var prefix = state.options.fileboxId + '_' + uuid;
                    $("#" + prefix + "_img img").attr("src", state.options.value[uuid].thumb);
                }
                utils.changeValue(state.filebox.prev()[0]);
                this.setProgress(uuid, 100, state);
            },
            error: function (uuid, error, state) {
                var options = state.options;
                if (options.onFail) {
                    options.onFail(this.progress[uuid].file, error);
                }
                $.messager.alert("上传失败", error, "error");
                this.setProgress(uuid, -1, state);
            },
            setProgress: function (uuid, progress, state) {
                var options = state.options,
                    prefix = options.fileboxId + '_' + uuid;
                if (progress == -1) {
                    if (this.progress[uuid].interval) {
                        clearInterval(this.progress[uuid].interval);
                        this.progress[uuid].interval = null;
                    }
                    $("#" + prefix + "_fileName").parent().addClass("error");
                    $("#" + prefix + "_progess").css("width", "100%");
                    switch (options.boxtype) {
                        case 'default':
                            $("#" + prefix + "_progess").addClass("error");
                            $("#" + prefix + "_fileName").next('.file-show-icon-reload').show();
                            break;
                        case 'image':
                            $("#" + prefix + "_progess").parents('.file-progress').addClass("error");
                            break;
                    }
                    this.progress[uuid].start = false;
                } else if (!this.progress[uuid].start) {
                    this.progress[uuid].progress = progress;
                    this.progress[uuid].start = true;
                    this.progress[uuid].interval = setInterval(function () {
                        ajaxUtil.progress[uuid].value += Math.floor(Math.random() * 10);
                        if (ajaxUtil.progress[uuid].value >= ajaxUtil.progress[uuid].progress) ajaxUtil.progress[uuid].value = ajaxUtil.progress[uuid].progress;
                        if (options.onProgress) options.onProgress(ajaxUtil.progress[uuid].value);
                        $("#" + prefix + "_progess").css("width", ajaxUtil.progress[uuid].value + "%");
                        switch (options.boxtype) {
                            case 'default':
                                if (ajaxUtil.progress[uuid].value == 100) {
                                    $("#" + prefix + "_progess").parent().hide();
                                }
                                break;
                            case 'image':
                                $("#" + prefix + "_progessText").text(ajaxUtil.progress[uuid].value + "%");
                                if (ajaxUtil.progress[uuid].value == 100) {
                                    $("#" + prefix + "_img .file-image-content").show();
                                    $("#" + prefix + "_img .file-upload-mask").remove();
                                    $("#" + prefix + "_img .file-progress").remove();
                                }
                                break;
                        }
                        if (ajaxUtil.progress[uuid].value == 100) {
                            clearInterval(ajaxUtil.progress[uuid].interval);
                            delete ajaxUtil.progress[uuid];
                        }
                    }, 200);
                } else {
                    this.progress[uuid].progress = progress;
                }
            },
        },
        fileboxCreate = {
            init: function (target) {
                var state = $.data(target, "filebox");
                var options = state.options;
                options.fileboxId = "filebox_" + utils.uuid();
                utils.formatData(options);
                if (Array.isArray(options.value)) options.multiple = true;
                if ($.data(target, "textbox")) {
                    $(target).removeClass("filebox-f");
                    state.filebox.remove();
                    $(target).removeData("textbox")
                }
                $(target).addClass("filebox-f").textbox(options);
                state.filebox = $(target).next().addClass("filebox");
                if (options.isDatagridShow) state.filebox.addClass("datagridShow");
                fileboxTemple.init(state);
                fileboxTemple.addItems(target, options, state.filebox);
                this.initFun(target);
                if (options.readonly) {
                    $(target).filebox("readonly", true);
                }
                $(target).next().on('contextmenu', function (e) {
                    e.preventDefault();
                    return false;
                });
                if (!options.isDownloadAllowed) {
                    $(target).next().addClass("isDownloadAllowed");
                }
            },
            initFun: function (target) {
                var state = $.data(target, "filebox"),
                    options = state.options;
                $("#" + options.fileboxId + "_file").change(function (e) {
                    e.stopPropagation();
                    if ($(this).val() != '') {
                        var files = $(this)[0].files;
                        if (options.multiple) {
                            for (var i = 0; i < files.length; i++) {
                                fileboxCreate.ajaxSave(state, files[i]);
                            }
                        } else {
                            fileboxCreate.clearValue(target);
                            fileboxCreate.ajaxSave(state, files[0]);
                        }
                        $(this).val('');
                    }
                });
                state.filebox.on("click", '.file-show-icon-del', function (e) {
                    e.stopPropagation();
                    var uuid = $(e.target).parent().attr("data-uuid");
                    fileboxCreate.delValue(target, uuid);
                });
                state.filebox.on("click", '.file-show-icon-reload', function (e) {
                    e.stopPropagation();
                    var uuid = $(e.target).parent().attr("data-uuid");
                    fileboxCreate.relodFile(state, uuid)
                });
                state.filebox.on("click", '.file-show', function (e) {
                    e.stopPropagation();
                    var uuid = $(e.target).attr("data-uuid") || $(e.target).parent().attr("data-uuid"),
                        item = options.value[uuid];
                    if (!ajaxUtil.progress[uuid] && options.isDownloadAllowed && item.name && item.download) {
                        fileboxCreate.download(item.name, item.download);
                    }
                });
                state.filebox.on("click", ".file-iamge-show", function (e) {
                    e.stopPropagation();
                    var uuid = $(this).attr("data-uuid")
                    fileboxTemple.createModel(target, uuid);
                });
            },
            download: function (text, url) {
                var a = top.document.createElement('a');
                var event = new MouseEvent('click');
                a.download = text;
                a.href = url;
                a.dispatchEvent(event);
            },
            ajaxSave: function (state, file) {
                var options = state.options;
                var uuid = utils.uuid();
                if (options.onStart) {
                    var boo = options.onStart(file);
                    if (boo === false) return false;
                }
                options.value[uuid] = {
                    name: file.name
                };
                var prefix = options.fileboxId + '_' + uuid;
                fileboxTemple.addItem(options, prefix, state.filebox, uuid, options.value[uuid]);
                $("#" + prefix + "_progess").css("width", "0%");
                switch (options.boxtype) {
                    case 'default':
                        $("#" + prefix + "_fileName").next('.file-show-icon-reload').hide();
                        $("#" + prefix + "_progess").parent().width($("#" + prefix + "_fileName").width() + 65).show();
                        break;
                    case 'image':
                        $("#" + prefix + "_img .file-image-content").hide();
                        $("#" + prefix + "_img .file-upload-mask").show();
                        var progress = $("#" + prefix + "_img .file-progress").show();
                        var interval = setInterval(function () {
                            clearInterval(interval);
                            progress.css("margin-top", -progress.height() / 2 + 'px');
                        }, 200);
                        break;
                }

                ajaxUtil.postFile(file, uuid, state);
            },
            getValue: function (options) {
                var data = options.multiple ? [] : {};
                for (var key in options.value) {
                    var item = options.value[key];
                    if (options.multiple) {
                        data.push({
                            mid: item.id,
                            fileId: item.id,
                            fileName: item.name,
                            thumbUrl: item.thumb,
                            htmlUrl: item.download,
							fileType: item.fileType,
                        });
                    } else {
                        data = {
                            mid: item.id,
                            fileId: item.id,
                            fileName: item.name,
                            thumbUrl: item.thumb,
                            htmlUrl: item.download,
							fileType: item.fileType,
                        };
                    }
                }
                if((!Array.isArray(data) && !data.mid && !data.fileId) || data.length == 0) data = "";
                return data;
            },
            //删除某个文件信息
            delValue: function (target, uuid) {
                var state = $.data(target, "filebox"),
                    options = state.options,
                    prefix = options.fileboxId + '_' + uuid;
                if (ajaxUtil.progress[uuid]) {
                    ajaxUtil.setProgress(uuid, -1, state);
                    delete ajaxUtil.progress[uuid];
                }
                delete options.value[uuid];
                utils.changeValue(target);
                $("#" + prefix + "_fileName").parent().remove();
                $("#" + prefix + "_progess").parent().remove();
                $("#" + prefix + "_img").remove();
                if (!options.multiple) {
                    var btn = state.filebox.find(".file-image");
                    btn.find(".file-font-show").removeAttr("style");
                    btn.show();
                    var interval = setInterval(function () {
                        clearInterval(interval);
                        btn.find(".file-font-show").css({
                            "margin-top": -btn.find(".file-font-show").height() / 2 + 'px',
                            'transform': 'none'
                        });
                    }, 200);
                }
            },
            //清空所有文件信息
            clearValue: function (target) {
                var state = $.data(target, "filebox"),
                    options = state.options;
                for (var key in options.value) {
                    this.delValue(target, key);
                }
            },
            relodFile: function (state, uuid) {
                var options = state.options,
                    prefix = options.fileboxId + '_' + uuid,
                    file = ajaxUtil.progress[uuid].file;
                $("#" + prefix + "_progess").css("width", "0%");
                $("#" + prefix + "_fileName").next('.file-show-icon-reload').hide();
                if (file) ajaxUtil.postFile(file, uuid, state);
            },
        },
        fileboxTemple = {
            init: function (state) {
                var options = state.options;
                if ((options.boxtype == 'image' || options.boxtype == 'image_multiple') && !options.accept) {
                    options.accept = 'image/*';
                }
                state.filebox.find(".textbox-text").css({
                    "position": "absolute",
                    "visibility": "hidden",
                    "z-index": '-2'
                });

                this[options.boxtype](state);
                var inputFile = $("<input type=\"file\">").appendTo(state.filebox);
                inputFile.attr("id", options.fileboxId + "_file").attr("accept", options.accept).attr("capture", options.capture);
                if (options.multiple) {
                    inputFile.attr("multiple", "multiple");
                }
            },
            default: function (state) {
                var options = state.options;
                var btn = $("<span class='file-btn file-default'><i class='file-btn-icon'></i>上传文件</span>").appendTo(state.filebox);
                btn.attr("id", options.fileboxId + "_btn");
                $("<div class='file-prompt' style='display: " + (options.prompt ? 'block' : 'none') + ";'>" + options.prompt + "</div>").appendTo(state.filebox);
                btn.click(function (e) {
                    if (!options.readonly) {
                        $("#" + options.fileboxId + "_file").click();
                    }
                });
                state.filebox.css({"height": 'auto'});
            },
            image: function (state) {
                var options = state.options,
                    width = options.boxWidth,
                    height = width;
                if (!options.multiple) {
                    if (state.filebox.attr("style").indexOf('height') == -1) {
                        state.filebox.height(state.filebox.width());
                    }
                    width = state.filebox.width();
                    height = state.filebox.height();
                } else {
					state.filebox.css({"white-space": 'break-spaces'});
				}
                state.filebox.css({"height": 'auto', 'width': 'auto'});
                var btn = $("<div class='file-btn file-image'><div class='file-font-show'><div class='file-font-show-icon'></div><div class='file-font-show-text'>" + (options.btnText ? options.btnText : "上传图片") + "</div></div></div>").appendTo(state.filebox);
                btn.attr("id", options.fileboxId + "_btn").height(height - 2).width(width - 2);
                btn.click(function (e) {
                    if (!options.readonly) {
                        $("#" + options.fileboxId + "_file").click();
                    }
                });
                btn.find(".file-font-show-icon").height(height * 0.23);
                btn.find(".file-font-show-text").css("font-size", 14 * height / 104 + 'px');
                $("<div class='file-prompt' style='display: " + (options.prompt ? 'block' : 'none') + ";'>" + options.prompt + "</div>").appendTo(state.filebox);
                var interval = setInterval(function () {
                    var boo = true;
                    $(state.filebox).parents().each(function () {
                        if ($(this).css("display") == "none") {
                            boo = false;
                            return false;
                        }
                    });
                    if (boo) {
                        clearInterval(interval);
                        btn.find(".file-font-show").css({
                            "margin-top": -btn.find(".file-font-show").height() / 2 + 'px',
                            'transform': 'none'
                        });
                    }
                }, 200);
            },
            addItems: function (target, options, filebox) {
                for (var key in options.value) {
                    this.addItem(options, options.fileboxId + '_' + key, filebox, key, options.value[key])
                }
                utils.changeValue(target);
            },
            addItem: function (options, prefix, filebox, uuid, item) {
                switch (options.boxtype) {
                    case 'default':
                        $("<div class='file-show' style='display: block;' data-uuid='" + uuid + "'><i class='file-show-icon'></i><span id='" + prefix + "_fileName'>" + item.name + "</span><i class='file-show-icon-reload'></i><i class='file-show-icon-del'></i></div>").appendTo(filebox);
                        $("<div class='file-upload-progress'><div id='" + prefix + "_progess'></div></div>").appendTo(filebox);
                        break;
                    case 'image':
                        var height = filebox.find('.file-image').height(),
                            width = filebox.find('.file-image').width(),
                            imgshow = $("<div class='file-iamge-show' id='" + prefix + "_img' data-uuid='" + uuid + "'><div class='file-image-content'><img src='" + item.thumb + "' style='width:100%;height:100%;'/></div></div>"),
                            mask = $("<div class='file-upload-mask'></div>").appendTo(imgshow),
                            del = $("<div class='file-show-icon-del'></div>").appendTo(imgshow),
                            progress = $("<div class='file-progress'><span id='" + prefix + "_progessText'>0%</span><div class='file-upload-progress'><div id='" + prefix + "_progess'></div></div></div>").appendTo(imgshow);
                        imgshow.height(height).width(width);
                        filebox.find(".file-image").before(imgshow);
                        progress.css("font-size", 14 * height / 104 + 'px');
                        progress.find(".file-upload-progress").css("height", 6 * height / 104 + 'px');
                        if (!options.multiple) {
                            filebox.find(".file-image").hide();
                        }
                        break;
                }
            },
            createModel: function (target, uuid) {
                var state = $.data(target, "filebox"),
                    options = state.options,
                    item = options.value[uuid],
                    src = item.download,
                    mask = $("<div class='filebox-bigImg-mask'></div>").appendTo($("body")),
                    model = $("<div class='filebox-bigImg-model'><div class='bigImg-model-content'><div class='bingImg-model-head'>" + item.name + "<i class='bigImg-del'></i>" + (options.isDownloadAllowed ? "<i title='下载' class='bigImg-downLoad'></i>" : "") + "</div><div class='bingImg-model-body'><img src='" + src + "' /></div></div></div>").appendTo($("body"));
                model.find(".bigImg-del").click(function () {
                    mask.remove();
                    model.remove();
                });
                model.find(".bigImg-downLoad").click(function () {
                    if (!ajaxUtil.progress[uuid] && options.isDownloadAllowed && item.name && item.download) {
                        fileboxCreate.download(item.name, item.download);
                    }
                });
                $(model).find("img").on('contextmenu', function (e) {
                    e.preventDefault();
                    return false;
                });
            },
        }
    $.fn.filebox = function (options, param) {
        if (typeof options == "string") {
            var fn = $.fn.filebox.methods[options];
            if (fn) {
                return fn(this, param);
            } else {
                return this.textbox(options, param);
            }
        }
        options = options || {};
        return this.each(function () {
            var state = $.data(this, "filebox");
            if (state) {
                $.extend(state.options, options);
            } else {
                $.data(this, "filebox", {
                    options: $.extend({}, $.fn.filebox.defaults, $.fn.filebox.parseOptions(
                        this), options)
                });
            }
            fileboxCreate.init(this);
        });
    };
    $.fn.filebox.methods = {
        options: function (jq) {
            var options = jq.textbox("options");
            return $.extend($.data(jq[0], "filebox").options, {
                width: options.width,
                originalValue: options.originalValue,
                disabled: options.disabled,
                readonly: options.readonly
            });
        },
        clear: function (jq) {
            return jq.each(function () {
                fileboxCreate.clearValue(this);
            });
        },
        reset: function (jq) {
            jq.each(function () {
                var state = $.data(this, "filebox");
                var options = state.options;
                fileboxCreate.clearValue(this);
                options.value = options.oldValue;
                fileboxTemple.addItems(this, options, state.filebox);
            });
            return jq;
        },
        setValue: function (jq, data) {
            jq.each(function () {
                fileboxCreate.clearValue(this);
                if (data) {
                    var state = $.data(this, "filebox");
                    var options = state.options;
                    if (typeof data == 'string' && data && typeof options.onInit == 'function') {
                        data = options.onInit(data);
                        if (typeof data == 'string' || !data) {
                            return;
                        }
                        data = utils.formatInitData(data);
                    } else if (typeof data == 'string') return;
                    options.value = data;
                    utils.formatData(options);
                    fileboxTemple.addItems(this, options, state.filebox);
                    if (options.readonly && options.boxtype == 'image' && options.multiple && state.filebox.find(".file-iamge-show").length > 0) {
                        $("#" + options.fileboxId + "_btn").hide();
                    }
                }
            });
            return jq;
        },
        getValue: function (jq) {
            var state = $.data(jq[0], "filebox");
            var options = state.options;
            return fileboxCreate.getValue(options)
        },
        readonly: function (jq, readonly) {
            var state = $.data(jq[0], "filebox"),
                options = state.options;
            options.readonly = readonly;
            $(jq).textbox("readonly", readonly);
            switch (options.boxtype) {
                case 'default':
                    if (readonly) {
                        $("#" + options.fileboxId + "_btn").hide();
                        state.filebox.find(".file-show-icon-del").hide();
                    } else {
                        $("#" + options.fileboxId + "_btn").show();
                        state.filebox.find(".file-show-icon-del").show();
                    }
                    break;
                case 'image':
                    if (readonly) {
                        if (options.multiple && state.filebox.find(".file-iamge-show").length > 0) {
                            $("#" + options.fileboxId + "_btn").hide();
                        } else {
                            $("#" + options.fileboxId + "_btn").css("cursor", "default");
                            $("#" + options.fileboxId + "_btn").find(".file-font-show").hide();
                        }
                        $(jq).next().find(".file-show-icon-del").hide();
                    } else {
                        if (options.multiple && state.filebox.find(".file-iamge-show").length > 0) {
                            $("#" + options.fileboxId + "_btn").show();
                        } else {
                            $("#" + options.fileboxId + "_btn").css("cursor", "pointer")
                            $("#" + options.fileboxId + "_btn").find(".file-font-show").show();
                        }
                        $(jq).next().find(".file-show-icon-del").show();
                    }
                    break;
            }
        }
    };
    $.fn.filebox.parseOptions = function (target) {
        var t = $(target);
        return $.extend({}, $.fn.textbox.parseOptions(target), $.parser.parseOptions(target, [
            "modelName",
            "accept",
            "boxtype",
            "capture",
            "separator"
        ]), {
            multiple: (t.attr("multiple") ? true : undefined)
        });
    };
    $.fn.filebox.defaults = $.extend({}, $.fn.textbox.defaults, {
        //url: "/filestore/item/save", //异步上传
        url: "/filestore/item/upload", //异步上传
        modelName: 'common',
        boxtype: "default",
        formmat: {
            id: 'fileId',
            name: 'fileName',
            thumb: 'thumbUrl',
            download: 'htmlUrl',
			fileType: "fileType",
        },
        isDatagridShow: false,
        boxWidth: 100,
        btnText: "",
        accept: "",
        capture: "",
        separator: ",",
        isDownloadAllowed: true,//是否允许下载或预览
        multiple: false,
        header: null,
        oldValue: null,
        onInit: null,//控件初始化值的处理
        onStart: null, //上传开始前的执行逻辑
        onProgress: null, //上传进度的回调函数
        onDone: null, //上传完成后的执行逻辑
        onFail: null, //上传失败后的执行逻辑
        onValidate: function(val){}, //验证上传文件是否正确合理
        onDelete: null //删除文件前
    });
})(jQuery);
